<template>
  <div class="video_upload">
    <el-upload
      class="upload-demo"
      drag
      action="#"
      :http-request="startUpload"
      :file-list="fileList"
      v-if="fileList.length < 1"
    >
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">
        将文件拖到此处，或
        <em>点击上传</em>
      </div>
    </el-upload>
    <div class="file_list_info" style="height: 50px;width: 510px;" v-if="fileList.length > 0">
      <div
        class="file_info"
        v-for="file in fileList"
        :key="file.uid"
        style="width: 100%; height: 100%"
      >
        <div style="float: left; width:50px;height: 50px">
          <i class="el-icon-video-camera" style="font-size:46px;color:aqua"></i>
        </div>
        <div style="float: right;width: 450px;height: 50px; font-size:1px">
          <div style="height: 35px">
            <div class="info_left" style="float: left">
              <span>{{file.name}}</span>
            </div>
            <div class="info_right" style="width: 140px; float: right">
              <span class="button" v-if="file.status ==='1'" @click="stopUplaod(file)">暂停</span>
              <span class="button" v-if="file.status ==='2'" @click="reUpload(file)">开始</span>
              <span class="button" v-if="file.status ==='3'" @click="reUpload(file)">重试</span>
              <span class="button">删除</span>
              <span>{{file.percentage}}%</span>
            </div>
          </div>
          <div class="buttom" style="height: 15px">
            <div v-if="file.status !== '1'">
              <span>{{getFileStatusMsg(file.status)}}</span>
            </div>
            <div v-if="file.status === '1'">
              <span>已上传: {{formatFileSize(file.totalLoaded)}}/{{formatFileSize(file.size)}}</span>
              <span>上传速度: {{file.speed}}</span>
              <span>剩余时间: {{file.estimateTime}}</span>
            </div>
            <el-progress :show-text="false" :percentage="file.percentage"></el-progress>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { fragmentUploadUrls } from "@/api/file";
import axios from "axios";

export default {
  props: {
    files: {},
  },
  data() {
    return {
      imgUploadUrl:
        process.env.VUE_APP_BASE_API + '/file/upload',
      status: "0", // 0上传完成 1上传中 2暂停 3错误 4等待上传
      fileList: this.files,
    };
  },
  methods: {
    getFileStatusMsg(status) {
      let msg = "";
      switch (status) {
        case "0":
          msg = "上传完成";
          break;
        case "2":
          msg = "暂停中";
          break;
        case "3":
          msg = "上传出错";
          break;
        case "4":
          msg = "等待上传";
          break;
      }
      return msg;
    },

    // 时间戳格式化
    formatSeconds(value) {
      let result = parseInt(value);
      let h =
        Math.floor(result / 3600) < 10
          ? "0" + Math.floor(result / 3600)
          : Math.floor(result / 3600);
      let m =
        Math.floor((result / 60) % 60) < 10
          ? "0" + Math.floor((result / 60) % 60)
          : Math.floor((result / 60) % 60);
      let s =
        Math.floor(result % 60) < 10
          ? "0" + Math.floor(result % 60)
          : Math.floor(result % 60);

      let res = "";
      if (h !== "00") res += `${h}h`;
      if (m !== "00") res += `${m}min`;
      res += `${s}s`;
      return res;
    },

    // 大小格式化
    formatFileSize(size) {
      var s = 0;
      s = size / (1024 * 1024 * 1024);
      if (s >= 1) {
        return Math.round(s) + "GB";
      }
      s = s * 1024;
      if (s >= 1) {
        return Math.round(s) + "MB";
      }
      s = s * 1024;
      return Math.round(s) + "kB";
    },

    // 获取上传信息（当前速度，剩余时间，已上传大小，进度）
    getUploadInfo(file, e) {
      let totalLoaded =
        (file.totalLoaded | 0) + e.loaded - (file.topLoaded | 0);
      file.totalLoaded = totalLoaded;
      let uoploadTime = Math.ceil(
        (e.timeStamp - (file.topTimeStamp | 0)) / 1000
      ); //上传时间
      let uoploadSize = Math.ceil(e.loaded - (file.topLoaded | 0)); //上传文件大小
      let speed = Math.ceil(uoploadSize / uoploadTime / 1024) + "KB/S"; //上传速度
      let estimateTime = Math.ceil(
        ((file.size - file.totalLoaded) / uoploadSize) * uoploadTime
      ); //剩余所需时间
      let percentage = Math.ceil(
        ((e.loaded / e.total + file.successIndex.length) * 100) /
          file.totalIndex.length
      ); //百分比进度
      file.percentage = percentage;
      file.speed = speed;
      file.estimateTime = this.formatSeconds(estimateTime);
      file.topLoaded = e.loaded;
      file.topTimeStamp = e.timeStamp;
      if (file.status === "4") {
        file.status = "1";
      }
      if (file.status === "1") {
        this.changeFileList();
      }
    },

    // 重新赋值 渲染页面
    changeFileList() {
      let newFileList = [];
      this.fileList.forEach((item) => {
        newFileList.push(item);
      });
      this.fileList = newFileList;
    },

    // 上传接口返回错误
    httpError(file, index) {
      file.status = "3";
      file.errorIndex.push(index);
      this.changeFileList();
    },

    uplaodSuccess(params) {
      this.$emit("success", params);
    },
    // 上传接口返回成功
    httpSuccess(file, i, shardIndex) {
      file.endTime = new Date().getTime();
      file.uploadTime = (file.endTime - file.startTime) / 1000; //分片上传时间 单位秒
      file.successIndex.push(shardIndex[i]);
      // 判断所有切片都上传成功
      if (file.successIndex.length === file.totalIndex.length) {
        file.status = "0";
        const params = { objectName: file.objectName, contentType: file.type };
        this.uplaodSuccess(params);
      }
      // 修改fileList
      this.changeFileList();
      i++;
      if (file.status === "1") {
        this.httpUpload(file, i, shardIndex);
      }
    },

    // 重新上传
    reUpload(file) {
      file.status = "4";
      // 需要上传的分片
      let shardIndex = [];
      file.totalIndex.forEach((element) => {
        if (file.successIndex.indexOf(element) < 0) {
          shardIndex.push(element);
        }
      });
      this.httpUpload(file, 0, shardIndex);
      return true;
    },

    // 暂停上传
    stopUplaod(file) {
      file.status = "2";
      this.changeFileList();
    },

    // 调用后台接口上传
    httpUpload(file, i, shardIndex) {
      // 获取切片文件
      const index = shardIndex[i];
      file.start = index.start;
      file.end = index.end;
      const shardFile = file.slice(file.start, file.end);
      // 请求参数
      file.topLoaded = 0;
      file.topTimeStamp = 0;
      axios
        .put(index.url, shardFile, {
          //添加请求头
          headers: { "Content-Type": "binary" },
          onUploadProgress: (e) => {
            this.getUploadInfo(file, e);
          },
        })
        .then(() => {
          this.httpSuccess(file, i, shardIndex);
        });
    },

    // 新增文件首次上传
    startUpload(param) {
      const file = param.file;
      this.fileList.push(file);
      file.successIndex = []; //已成功上传的分片
      file.errorIndex = []; //上传失败的分片
      file.status = "4";
      file.percentage = 0;
      // 需要上传的分
      let data = new FormData();
      data.append("file", file);
      fragmentUploadUrls(data).then((v) => {
        if (v.code === 200) {
          file.totalIndex = v.data.urls; //所有分片
          file.status = "1";
          file.objectName = v.data.objectName;
          this.httpUpload(file, 0, v.data.urls);
        }
      });
    },
  },
};
</script>



<style lang="scss" scoped>
.video_upload {
  padding: 10px 0;
  .buttom {
    span {
      margin-right: 20px;
    }
  }
  .info_right {
    span {
      margin-left: 20px;
    }
    .button {
      visibility: hidden;
      cursor: pointer;
    }
  }
  .info_right :hover {
    color: chocolate;
  }

  .file_list_info :hover {
    .info_right {
      .button {
        visibility: visible;
      }
    }
  }
}
</style>